package com.yycx.starter.redis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.starter.redis.core.RedisKeyChangeListener;
import com.yycx.starter.redis.core.RedisMessageListener;
import com.yycx.starter.redis.listener.RedisKeyChangeHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * redis配置类
 *
 * @author zyf
 */
@Slf4j
@Configuration
@ConditionalOnClass({RedisConnectionFactory.class, RedisTemplate.class})
public class RedisConfig {

    @Resource
    private RedisConnectionFactory redisConnectionFactory;

    @Resource
    private RedisKeyChangeHandler redisKeyChangeHandler;

    @Autowired(required = false)
    private List<RedisKeyChangeListener> redisKeyChangeListeners;


    @Autowired(required = false)
    private List<RedisMessageListener> redisMessageListeners;


    /**
     * 指定服务器该发送哪些类型的通知
     * K(键空间通知,以__keyspace@<db>为前缀)
     * E(键事件通知,以__keyevent@<db>为前缀)
     * g(DEL,EXPIRE,RENAME等类型无关的通用命令通知)
     * $
     */
    private String keyspaceNotificationsConfigParameter = "KEA";


    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        log.info("初始化RedisMessageListenerContainer");
        initRedisMessageListener(container);
        //container.addMessageListener(commonListenerAdapter, new ChannelTopic("minio_user_add"));
        return container;
    }


    public void initRedisMessageListener(RedisMessageListenerContainer listenerContainer) {
        if (StringUtils.hasText(keyspaceNotificationsConfigParameter)) {
            RedisConnection connection = listenerContainer.getConnectionFactory().getConnection();
            try {
                Properties config = connection.getConfig("notify-keyspace-events");
                if (StringUtils.hasText(config.getProperty("notify-keyspace-events"))) {
                    connection.setConfig("notify-keyspace-events", keyspaceNotificationsConfigParameter);
                }

            } finally {
                connection.close();
            }
        }
        if (FlymeUtils.isNotEmpty(redisKeyChangeListeners)) {
            List<Topic> listTopic = new ArrayList<>();
            for (RedisKeyChangeListener redisKeyChangeListener : redisKeyChangeListeners) {
                Topic topic = new PatternTopic(RedisKeyChangeHandler.TOPIC_KEY_SPACE_PRE + redisKeyChangeListener.getTopicName());
                listTopic.add(topic);
            }
            // 注册消息监听
            listenerContainer.addMessageListener(redisKeyChangeHandler, listTopic);
        }

        if (FlymeUtils.isNotEmpty(redisMessageListeners)) {
            for (RedisMessageListener redisMessageListener : redisMessageListeners) {
                Topic topic = new ChannelTopic(redisMessageListener.getTopicName());
                MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(redisMessageListener, "onMessage");
                messageListenerAdapter.afterPropertiesSet();
                Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = this.jacksonSerializer();
                messageListenerAdapter.setSerializer(jackson2JsonRedisSerializer);
                listenerContainer.addMessageListener(messageListenerAdapter, topic);
            }
        }
    }


//
//    @Bean
//    MessageListenerAdapter commonListenerAdapter(MinioAddUserListener2 minioAddUserListener2) {
//        MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(minioAddUserListener2, "onMessage");
//        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = this.jacksonSerializer();
//        messageListenerAdapter.setSerializer(jackson2JsonRedisSerializer);
//        return messageListenerAdapter;
//    }

    private Jackson2JsonRedisSerializer jacksonSerializer(){
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        return jackson2JsonRedisSerializer;
    }


}
